//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0

#include "app_bootloader.h"
#include <string.h>

typedef struct
{
    uint16_t length;
    uint8_t  buffer[DEBUG_Max_Buff_Count];
}Receive_Buffer_t;


static const Bootloader_t Bootloader = Bootloader_Default_Value;
static const Partition_Table_t Partition_Table = Partition_Table_Defalut_Value;



static Receive_Buffer_t* Get_RS485_Data(void)
{
    static Receive_Buffer_t Receive_Buffer;

    Receive_Buffer.length = WHT_Debug_Driver.WHT_Scanf(Receive_Buffer.buffer, sizeof(Receive_Buffer.buffer), 0xffffffff);
    return Receive_Buffer.length > 2 ? &Receive_Buffer : NULL;
}


// 跳转到Bootloader的函数
void Jump_To_Bootloader(void)
{
    // 关闭所有中断
    __disable_irq();
    
    // 清除所有挂起的中断
    SCB->ICSR |= SCB_ICSR_PENDSVCLR_Msk;
    
    // 设置栈顶指针
    __set_MSP(*((uint32_t*)0x00000000));  // Bootloader的栈顶地址
    
    // 获取Bootloader的复位向量
    void (*BootloaderResetHandler)(void) = (void (*)(void))(*((uint32_t*)0x00000004));
    
    // 跳转到Bootloader
    BootloaderResetHandler();
}

// 跳转到应用程序
void Jump_To_APP(void)
{
    typedef void (*app_entry_t)(void);
    app_entry_t app_entry;

    // 禁用所有中断
    __disable_irq();

    // 清除所有挂起的中断
    for(int i = 0; i < 8; i++)
    {
        NVIC->ICER[i] = 0xFFFFFFFF; // 禁用中断
        NVIC->ICPR[i] = 0xFFFFFFFF; // 清除中断挂起
    }

    // 禁用SysTick和其他可能的系统定时器
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL = 0;

    // 重置所有外设(可选)
    RCC_DeInit();

    // 设置主堆栈指针(MSP)
    __set_MSP(*(uint32_t*)Partition_Table.app_pos);

    // 获取应用程序入口地址（向量表的第二个字）
    app_entry = (app_entry_t)(*(uint32_t*)(Partition_Table.app_pos + 4));
    
    // 跳转到应用程序
    app_entry();
}

// 检查应用程序是否有效
bool Check_APP_Valid(void)
{
    // 检查栈顶指针是否在RAM范围内
    if((*(uint32_t*)Partition_Table.app_pos & 0x2FFE0000) != 0x20000000)
    {
        return false;
    }
    
    // 检查复位向量是否在Flash范围内
    uint32_t reset_vector = *(uint32_t*)(Partition_Table.app_pos + 4);
    if(reset_vector < Partition_Table.bootloader_pos || reset_vector > Partition_Table.bootloader_pos + Partition_Table.flash_size)
    {
        return false;
    }
    
    return true;
}

// 检查是否进入Bootloader模式
bool Check_Bootloader_Mode(void)
{
    //return true;
    return false;
}




// 发送报文出去
static void Send_Message_CRC16(Message_t* message)
{
    static uint16_t CRC16;
    
    CRC16 = CRC16_MODBUS_Calculate((uint8_t*)message, sizeof(Message_t) + message->buffer_length - 2);
    message->buffer[message->buffer_length] = CRC16 & 0xff;
    message->buffer[message->buffer_length + 1] = CRC16 >> 8;
    WHT_Debug_Driver.WHT_Printf((const char*)message, sizeof(Message_t)+ message->buffer_length);
}

// 处理Bootloader协议
void Handle_Bootloader(void)
{
    static Receive_Buffer_t* Receive_Buffer;
    static uint8_t Send_Buffer[DEBUG_Max_Buff_Count];
    static Message_t* Receive_Message;
    #define Send_Message ((Message_t *)Send_Buffer)

    static FunctionalState ADvanced = DISABLE;
    static ErrorStatus Erase_State = SUCCESS;
    static ErrorStatus Program_State = SUCCESS;

    static uint32_t Temp_Data;

    for (; ;)
    {
        for (; ;)
        {
            WHT_Delay_ms(20);            
            Receive_Buffer = Get_RS485_Data();
            if (Receive_Buffer != NULL)
            {
                Receive_Message = (Message_t*)Receive_Buffer->buffer;
                break;
            }
        }

        if ((Receive_Message->addr != 1) ||  (Receive_Message->dir != Dir_PC))
        {
            continue;
        }
        if (CRC16_MODBUS_Lookup(Receive_Buffer->buffer, Receive_Buffer->length) != 0)
        {
            continue;
        }
        
        Send_Message->addr = Receive_Message->addr;
        Send_Message->dir = Dir_MCU;
        Send_Message->cmd = Receive_Message->cmd;
        switch (Receive_Message->cmd)
        {
        case Set_BaudRate://临时设置波特率，默认115200密钥
            Temp_Data = Receive_Message->buffer[0] << 0;
            Temp_Data |= Receive_Message->buffer[1] << 8;
            Temp_Data |= Receive_Message->buffer[2] << 16;
            Temp_Data |= Receive_Message->buffer[3] << 24;

            Send_Message->buffer_length = 1;
            Send_Message->buffer[0] = SUCCESS;
            Send_Message_CRC16(Send_Message);
            WHT_Delay_ms(3);
            WHT_Debug_Driver.WHT_Init(Temp_Data);
            break;
        case Get_Boot_Inof://获取boot信息
            Send_Message->buffer_length = sizeof(Bootloader);
            memcpy(Send_Message->buffer, (void*)&Bootloader, sizeof(Bootloader));
            Send_Message_CRC16(Send_Message);
            break;
        case Get_Partition_Table_Info://获取分区表信息
            Send_Message->buffer_length = sizeof(Partition_Table);
            memcpy(Send_Message->buffer, (void*)&Partition_Table, sizeof(Partition_Table));
            Send_Message_CRC16(Send_Message);
            break;
        case Get_Public_Data://获取共享数据
            break;
        case Reboot://重启boot
            NVIC_SystemReset();
            break;
        case RunApp://运行app
            Send_Message->buffer_length = 1;
            Send_Message->buffer[0] = Check_APP_Valid() == true ?  SUCCESS : ERROR;
            Send_Message_CRC16(Send_Message);
            WHT_Delay_ms(2);
            if(Send_Message->buffer[0] == SUCCESS)
            {
                Jump_To_APP();
            }
            break;
        case Account_Login://账号登录，默认admin,admin
            if (strncmp((const char*)Receive_Message->buffer, "admin\r\nadmin", 12) == 0)
                ADvanced = ENABLE;
            else
                ADvanced = DISABLE;
            Send_Message->buffer_length = 1;
            Send_Message->buffer[0] = ADvanced == ENABLE ?  SUCCESS : ERROR;
            Send_Message_CRC16(Send_Message);
            break;
        case Erase_Page://擦除指定页
            __disable_irq();
            Erase_State = WHT_Flash_BSP_Erase_And_Check(Receive_Message->buffer[0], 1);
            __enable_irq();

            Send_Message->buffer_length = 1;
            Send_Message->buffer[0] = Erase_State;
            Send_Message_CRC16(Send_Message);
            break;
        case Get_Erase_State://获取擦除状态
            break;
        case Program_Addr://烧录
            Temp_Data = Receive_Message->buffer[0] << 0;
            Temp_Data |= Receive_Message->buffer[1] << 8;
            Temp_Data |= Receive_Message->buffer[2] << 16;
            Temp_Data |= Receive_Message->buffer[3] << 24;
            __disable_irq();
            Program_State = WHT_Flash_BSP_Write(Temp_Data, &Receive_Message->buffer[4], Receive_Message->buffer_length - 4);
            __enable_irq();   // 恢复全局中断
            Send_Message->buffer_length = 1;
            Send_Message->buffer[0] = Program_State;
            Send_Message_CRC16(Send_Message);
            break;
        default:
            break;
        }
    }
}




